package org.bluedream.core.module.service.bill.stkIn;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.apache.commons.collections.map.HashedMap;
import org.bluedream.comm.base.bill.BillBodyEntity;
import org.bluedream.comm.utils.CreateGUIDUtil;
import org.bluedream.comm.utils.EmptyUtil;
import org.bluedream.comm.utils.RestResult;
import org.bluedream.comm.utils.excel.ExcelUtil;
import org.bluedream.core.module.base.BillServiceImpl;
import org.bluedream.core.module.dao.bill.stkIn.StkInDao;
import org.bluedream.core.module.entity.bill.stkIn.StkIn;
import org.bluedream.core.module.entity.bill.stkIn.dtl.StkInDtl;
import org.bluedream.core.module.entity.goods.Goods;
import org.bluedream.core.module.entity.goods.Product;
import org.bluedream.core.module.entity.stock.SkuStock;
import org.bluedream.core.module.entity.stock.TmpSkuStock;
import org.bluedream.core.module.service.bill.OddImportService;
import org.bluedream.core.module.service.bill.stkIn.dtl.StkInDtlService;
import org.bluedream.core.module.service.goods.GoodsService;
import org.bluedream.core.module.service.goods.ProductService;
import org.bluedream.core.module.service.goods.SupplierService;
import org.bluedream.core.module.service.stock.SkuStockService;
import org.bluedream.core.module.service.stock.TmpSkuStockService;
import org.bluedream.core.module.service.warehouse.WareHouseService;
import org.bluedream.core.utils.DictUtil;
import org.bluedream.core.utils.UserUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.Serializable;
import java.sql.Date;
import java.util.List;
import java.util.Map;

/**
 * @ClassName StkInService
 * @Description TODO
 * @Author foxsand
 * @Data 2021-11-18 15:23
 * @Version
 */
@Service
@DS("master")
@Transactional(
        readOnly = true
)
public class StkInService extends BillServiceImpl<StkInDao, StkIn> implements IService<StkIn> {
    private static final Logger logger = LoggerFactory.getLogger(StkInService.class);

    @Resource
    private StkInDtlService stkInDtlService;

    @Resource
    private SupplierService supplierService;

    @Resource
    private WareHouseService wareHouseService;

    @Resource
    private SkuStockService skuStockService;

    @Resource
    private OddImportService oddImportService;

    @Resource
    private TmpSkuStockService tmpSkuStockService;

    @Resource
    private ProductService productService;

    @Resource
    private GoodsService goodsService;

    @Override
    public StkIn getById(Serializable id) {
        if (EmptyUtil.isEmpty(id)){
            return new StkIn();
        }
        return super.getById(id);
    }

    public IPage<StkIn> findPage(StkIn entity, String... args) {
        String tableName = entity.getClass().getSimpleName();
        Map<String , Object> search = new HashedMap();
        String billType = DictUtil.getDictValue("sys.bill.type", entity.getBillTypeLabel(), "");
        search.put(tableName + ".bill_type;eq" , billType);
        try {
            if (EmptyUtil.isNoEmpty(entity.getGeCreateDate())){
                search.put(tableName + ".create_date;ge" , Date.valueOf(entity.getGeCreateDate()));
            }
            if (EmptyUtil.isNoEmpty(entity.getLtCreateDate())){
                search.put(tableName + ".create_date;lt" , Date.valueOf(entity.getLtCreateDate()));
            }
            if (EmptyUtil.isNoEmpty(entity.getGeCheckDate())){
                search.put(tableName + ".check_date;ge" , Date.valueOf(entity.getGeCheckDate()));
            }
            if (EmptyUtil.isNoEmpty(entity.getLtCheckDate())){
                search.put(tableName + ".check_date;lt" , Date.valueOf(entity.getLtCheckDate()));
            }
            if (EmptyUtil.isNoEmpty(entity.getStatus())){
                search.put(tableName + ".status;eq" , entity.getStatus());
            }
            if (EmptyUtil.isNoEmpty(entity.getBillNum())){
                search.put(tableName + ".bill_num" , entity.getBillNum());
            }
            if (EmptyUtil.isNoEmpty(entity.getWarCode())){
                search.put(tableName + ".war_code" , entity.getWarCode());
            }
            if (EmptyUtil.isNoEmpty(entity.getSupplierCode())){
                search.put(tableName + ".supplier_Code;eq" , entity.getSupplierCode());
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        return super.findPage(entity , true , search , args);
    }

    @Transactional(
            readOnly = false,
            isolation = Isolation.SERIALIZABLE,
            rollbackFor = Exception.class
    )
    public RestResult saveEntity(StkIn entity){
        try {
            if (entity.getIsNewRecord()){
                String billType = DictUtil.getDictValue("sys.bill.type", "采购入库单", "");
                String billNum = oddImportService.getNowBillNum(billType);
                entity.setBillNum(billNum);
                entity.setBillType(billType);
                String billId = CreateGUIDUtil.GenerateGUID();
                entity.setId(billId);

                for (StkInDtl body:entity.getStkInDtlList()
                ) {
                    String errorMsg = super.isCheckSkuQty(UserUtil.getLoginOrgCode() , entity.getWarCode() , body.getCode() , body.getQty() , 1);
                    if (EmptyUtil.isNoEmpty(errorMsg)){
                        return RestResult.error(errorMsg);
                    }
                    body.setBillNum(billNum);
                    body.setBillType(billType);
                    tmpSkuStockService.save(new TmpSkuStock(billId, billType, 1 , billNum, body.getQty(), body.getTotal(), body.getCode(), entity.getWarCode()));

                }
                oddImportService.save(billType , billNum);
            }
            super.save(entity);
            stkInDtlService.saveBatch(entity.getStkInDtlList());
        }catch (Exception e1){
            e1.printStackTrace();
            logger.error(e1.getMessage());
            //todo:@Transactional和try catch捕获异常会让注解失效
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResult.error("数据保存失败:" + e1.getMessage());
        }
        return RestResult.ok();
    }

    @Transactional(
            readOnly = false,
            isolation = Isolation.SERIALIZABLE,
            rollbackFor = Exception.class
    )
    public RestResult check(StkIn entity){
        try {
            entity = this.getById(entity.getId());

            /*
            dtl 明细数据写入库存表
             */
            List<StkInDtl> dtlList = stkInDtlService.listByHead(entity.getBillNum() , entity.getBillType() , entity.getOrgCode(), new StkInDtl());



            for (StkInDtl ob1:dtlList
            ) {
                QueryWrapper<SkuStock> stockQueryWrapper = new QueryWrapper<>();
                stockQueryWrapper.eq("war_code" , entity.getWarCode());
                stockQueryWrapper.eq("org_code" , entity.getOrgCode());
                stockQueryWrapper.eq("code" , ob1.getCode());
                /**
                 * type = 0 库存减少  type = 1 库存增加
                 */
                skuStockService.saveByBill(stockQueryWrapper , "1" , ob1.getCode() , entity.getWarCode() , ob1.getQty() , ob1.getTotal());
            }

            super.setCheckAttribute(entity);
            super.save(entity);
            /*
            从临时库存表中删除已记账明细
             */
            tmpSkuStockService.delete(entity.getId() , entity.getBillNum() , entity.getBillType() , entity.getOrgCode());
        }catch (Exception e){
            e.printStackTrace();
            logger.error(e.getMessage());
            //todo:@Transactional和try catch捕获异常会让注解失效
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResult.error("单据记账失败，单号：" + entity.getBillNum() + "! error message:" + e.getMessage());
        }

        return RestResult.ok("单据：" + entity.getBillNum() + "已记账");
    }

    /**
     * 手动开启事务提交，
     * @param file
     * @return
     */
    public IPage<StkInDtl>  excelImport(MultipartFile file){
        try {
            List<StkInDtl> dtlList = ExcelUtil.import2List(file , 0 , StkInDtl.class , 0);
            String msgStatus = "";
            for (StkInDtl v0:dtlList
            ) {
                try {
                    QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("org_code" , UserUtil.getLoginOrgCode());
                    queryWrapper.eq("barcode" , v0.getBarcode());
                    Product p1 = productService.getOne(queryWrapper);
                    Goods g1 = goodsService.getById(p1.getId());
                    v0.setCode(p1.getCode());
                    v0.setQpc(p1.getQpc());
                    v0.setQpcStr(p1.getQpcStr());
                    v0.setName(g1.getName());
                    v0.setOprice(p1.getOprice());
                    v0.setTotal(v0.getQty().multiply(p1.getOprice()));
                }catch (Exception e1){
                    e1.printStackTrace();
                    System.out.println(e1.getMessage());
                }
            }
            IPage<StkInDtl> page = new Page<>();
            page.setRecords(dtlList);
            page.setCurrent(1L);
            page.setTotal(dtlList.size());
            page.setSize(dtlList.size());
            return page;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}
